package com.newtouch.bxzs.account.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.newtouch.bxzs.account.mapper.UserMapper;
import com.newtouch.bxzs.account.model.UserDetailsBO;
import com.newtouch.bxzs.account.model.UserLoginVO;
import com.newtouch.bxzs.account.model.UserRegisterVO;
import com.newtouch.bxzs.account.service.UserService;
import com.newtouch.bxzs.common.base.BaseErrorEnum;
import com.newtouch.bxzs.common.base.BaseException;
import com.newtouch.bxzs.common.base.em.SystemParamsEnum;
import com.newtouch.bxzs.common.base.em.UserFlagEnum;
import com.newtouch.bxzs.common.base.model.User;
import com.newtouch.bxzs.common.base.model.bo.UserMenuListBO;
import com.newtouch.bxzs.common.base.model.vo.GetUserMenuListVO;
import com.newtouch.bxzs.common.base.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 登录用户Service实现类
 *
 * <p>
 * <b>History:</b>
 * <table border="1">
 * <tr>
 * <th>Date</th>
 * <th>Operator</th>
 * <th>Memo</th>
 * </tr>
 * <tr>
 * <td>2021年1月13日</td>
 * <td>Amour</td>
 * <td>Create</td>
 * </tr>
 * </table>
 *
 * @author Amour
 * @version 1.0.0
 * @since 1.0.0
 */
@Service
public class UserServiceImpl implements UserService {

    /**
     * 静态变量：系统日志
     */
    private static final Log logger = LogFactory.getLog(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisUtils redisUtils;

    /*
     * (non-Javadoc)
     *
     * @see
     * com.newtouch.bxzs.account.service.UserService#login4Pc(com.newtouch.bxzs.
     * account.model.PcUserLoginVO)
     */
    @Override
    public User login4Pc(String username, String password, Integer userFlag, Integer loginDefultNumber,
                         Integer lockTime) {
        logger.info(username + "用户登录");
        Assert.notEmpty(username, "参数【用户名】不能为空");
        Assert.notEmpty(password, "参数【密码】不能为空");
        Assert.notEmpty(userFlag, "参数【用户标识】不能为空");
        // 根据用户名查询后台用户是否存在
        QueryWrapper<User> query = new QueryWrapper<>();
        query.eq("USER_LOGIN_ACCOUNT_NUMBER", username);
        User user = userMapper.selectOne(query);
        if (BeanUtil.isEmpty(user)) {
            logger.error(username + BaseErrorEnum.USER_NOT_EXISTS.getResultMsg());
            throw new BaseException(BaseErrorEnum.USER_NOT_EXISTS);
        }
        // PC端需要验证权限
        if (UserFlagEnum.PC_FLAG.getCode().equals(userFlag) && !user.getPlatformManagementUserFlag()) {
            logger.error(username + BaseErrorEnum.USER_NOT_PERMISSION.getResultMsg());
            throw new BaseException(BaseErrorEnum.USER_NOT_PERMISSION);
        }
        // 验证密码是否正确
        if (!MD5Util.verifyPassword(password, user.getUserLoginPassword())) {
            logger.error(username + "密码错误");
            // 更新缓存
            loginDefultNumber++;
            redisUtils.set(username, String.valueOf(loginDefultNumber), lockTime == null ? 30 : lockTime,
                    TimeUnit.MINUTES);
            throw new BaseException(BaseErrorEnum.PASSWORD_ERROR);
        }
        return user;
    }

    /*
     * (non-Javadoc)
     *
     * @see com.newtouch.bxzs.account.service.UserService#getMenuList(java.lang.
     * String, java.lang.String)
     */
    @Override
    public List<UserMenuListBO> getMenuList(String userId, String terminalType) {
        GetUserMenuListVO menuVO = new GetUserMenuListVO();
        menuVO.setUserId(userId);
        menuVO.setTerminalType(String.valueOf(terminalType));
        return userMapper.getUserMenuList(menuVO);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.newtouch.bxzs.account.service.UserService#login4Pc(com.newtouch.bxzs.
     * account.model.UserLoginVO)
     */
    @Override
    public User login4Pc(UserLoginVO userLoginVO, Integer loginDefultNumber,
                         Integer lockTime) {
        logger.info(userLoginVO.getUsername() + "用户登录");
        // 根据用户名查询后台用户是否存在
        QueryWrapper<User> query = new QueryWrapper<>();
        query.eq("USER_LOGIN_ACCOUNT_NUMBER", userLoginVO.getUsername());
        User user = userMapper.selectOne(query);
        if (BeanUtil.isEmpty(user)) {
            logger.error(userLoginVO.getUsername() + BaseErrorEnum.USER_NOT_EXISTS.getResultMsg());
            throw new BaseException(BaseErrorEnum.USER_NOT_EXISTS);
        }
        if (StringUtils.isEmpty(user.getUserLoginHandPass())) {
            throw new BaseException(BaseErrorEnum.NO_HAND_PASS);
        }
        // 验证手势密码是否正确
        if (!MD5Util.verifyPassword(userLoginVO.getHandPass(), user.getUserLoginHandPass())) {
            logger.error(userLoginVO.getUsername() + "手势密码错误");
            // 更新缓存
            loginDefultNumber++;
            redisUtils.set(userLoginVO.getUsername(),
                    String.valueOf(loginDefultNumber),
                    lockTime == null ? 30 : lockTime, TimeUnit.MINUTES);
            throw new BaseException(BaseErrorEnum.PASSWORD_ERROR);
        }
        return user;
    }

    @Override
    public User register(UserRegisterVO userRegisterVO) {
        // 判断传入参数是否为空
        if (BeanUtil.isEmpty(userRegisterVO)) {
            return null;
        }
        // 判断是否存在已注册用户
        User currentUser = userMapper.selectOne(
                new QueryWrapper<User>()
                        .eq("USER_CERTIFICATE_TYPE", userRegisterVO.getUserCertificateType()).
                        eq("USER_CERTIFICATE_NUMBER", userRegisterVO.getUserCertificateNumber()));
        if (!BeanUtil.isEmpty(currentUser)) {
            throw new BaseException(BaseErrorEnum.DATA_EXISTS);
        }
        // 判断手机号是否已被注册
        checkUserPhone(userRegisterVO.getUserPhone());
        User user = new User();
        // 校验证件
        CheckCertificateTypeUtil.checkCertificate(userRegisterVO.getUserCertificateType(), userRegisterVO.getUserCertificateNumber());
        // 验证手机号
        if (!Validator.isMobile(userRegisterVO.getUserPhone())) {
            throw new BaseException(BaseErrorEnum.BODY_NOT_MATCH);
        }
        // 调模拟端获取用户信息
        if (!StringUtils.isEmpty(userRegisterVO.getUserCertificateNumber())) {
            //银行or保险
            userRegisterVO.setOrganType(redisUtils.get(SystemParamsEnum.BANKING_OR_INSURANCE.getCode()));
            SendHttpRequestUtils<UserRegisterVO> sendHttpRequestUtils = new SendHttpRequestUtils<>();
            JSONObject response = sendHttpRequestUtils.sendHttpRequestToJson(userRegisterVO, redisUtils.get(SystemParamsEnum.REGISTER.getCode()));
            UserDetailsBO userDetails = JSONObject.toJavaObject(response, UserDetailsBO.class);
            //将模拟端接收到数据copy到user
            BeanUtils.copyProperties(userDetails, user);
        }
        // 将密码MD加密后存入数据库
        user.setUserLoginPassword(MD5Util.getMD5ofStr(userRegisterVO.getUserLoginPassword()));
        user.setUserLoginAccountNumber(userRegisterVO.getUserPhone());
        user.setUserPhone(userRegisterVO.getUserPhone());
        user.setUserCertificateType(userRegisterVO.getUserCertificateType());
        user.setUserCertificateNumber(userRegisterVO.getUserCertificateNumber());
        user.setAttribute();
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        // 注册
        userMapper.insert(user);
        return user;
    }

    @Override
    public User loginByUnifiedAuth(UserLoginVO userLoginVO, Integer loginDefaultNumber, Integer lockTime) {
        logger.info(userLoginVO.getUsername() + "用户登录");
        Assert.notEmpty(userLoginVO.getUsername(), "参数【用户名】不能为空");
        Assert.notEmpty(userLoginVO.getPassword(), "参数【密码】不能为空");
        Assert.notEmpty(userLoginVO.getUserFlag(), "参数【用户标识】不能为空");
        // 调用模拟端,统一认证平台
        SendHttpRequestUtils<UserLoginVO> sendHttpRequestUtils = new SendHttpRequestUtils<>();
        Object res = sendHttpRequestUtils.sendHttpRequest(userLoginVO, redisUtils.get(SystemParamsEnum.UNIFIED_AUTHENTICATION.getCode()));
        if ("true".equals(res.toString())) {
            QueryWrapper<User> query = new QueryWrapper<>();
            query.eq("USER_LOGIN_ACCOUNT_NUMBER", userLoginVO.getUsername());
            User user = userMapper.selectOne(query);
            // 判断用户是否存在
            if (BeanUtil.isEmpty(user)) {
                logger.error(userLoginVO.getUsername() + BaseErrorEnum.USER_NOT_EXISTS.getResultMsg());
                throw new BaseException(BaseErrorEnum.USER_NOT_EXISTS);
            }
            // PC端需要验证权限
            if (UserFlagEnum.PC_FLAG.getCode().equals(userLoginVO.getUserFlag()) && !user.getPlatformManagementUserFlag()) {
                logger.error(userLoginVO.getUsername() + BaseErrorEnum.USER_NOT_PERMISSION.getResultMsg());
                throw new BaseException(BaseErrorEnum.USER_NOT_PERMISSION);
            }
            // 验证密码是否正确
            if (!MD5Util.verifyPassword(userLoginVO.getPassword(), user.getUserLoginPassword())) {
                logger.error(userLoginVO.getUsername() + "密码错误");
                // 更新缓存
                loginDefaultNumber++;
                redisUtils.set(userLoginVO.getUsername(), String.valueOf(loginDefaultNumber), lockTime == null ? 30 : lockTime,
                        TimeUnit.MINUTES);
                throw new BaseException(BaseErrorEnum.PASSWORD_ERROR);
            }
            return user;
        } else {
            throw new BaseException(BaseErrorEnum.AUTHENTICATION);
        }
    }

    @Override
    public String checkUserPhone(String userPhone) {
        if (StringUtils.isEmpty(userPhone)) {
            return null;
        }
        QueryWrapper<User> query = new QueryWrapper<>();
        query.eq("USER_PHONE", userPhone);
        User user = userMapper.selectOne(query);
        if (BeanUtil.isEmpty(user)) {
            throw new BaseException(BaseErrorEnum.USER_NOT_EXISTS);
        } else {
            return userPhone;
        }
    }

    @Override
    public Integer updateLoginPassword(String userPhone, String password, String confirmPassword) {
        if (StringUtils.isEmpty(userPhone)) {
            return null;
        }
        // 判断两次密码是否一致
        if (!password.equals(confirmPassword)) {
            throw new BaseException(BaseErrorEnum.PASSWORD_DIFFERENT);
        }
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.eq("USER_PHONE", userPhone);
        User user = userMapper.selectOne(qw);
        // 密码加密
        user.setUserLoginPassword(MD5Util.getMD5ofStr(password));
        user.setUpdateTime(new Date());

        return userMapper.update(user, qw);
    }

    @Override
    public Boolean checkCertificate(String certificateType, String certificateNumber) {
        if (StringUtils.isEmpty(certificateType) || StringUtils.isEmpty(certificateNumber)){
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        CheckCertificateTypeUtil.checkCertificate(certificateType,certificateNumber);
        return true;
    }
}
